/**
 * OverView: 数据请求中心
 * Author: Zhaomi
 * Date: 13-5-13 下午2:49
 * Email: yanyuetian@gmail.com
 * Create By JetBrains WebStorm.
 */
var BaseConf = require("../base-conf.js");
var NativeApp = require("../phonegap/native-bridge.js");
var Imports = require("../utils/imports.js");
var LoadFrame = require("../ui/load-frame.js");
var loadTipTpl = Imports("text!../page-layout/common/loadtips.html");
var targetHeight = 800;
var doc = document;

var App={
    Routes: {},
    Modules: {},
    PreSeed: 97,
    KeyToModuleName: {},        //数据key到模块名称的映射
    BuildContent: {},         //原始请求参数
    UpdateState: 0,           //请求参数是否应该发生变化
    Requester: {}             //数据请求模块
};

App.asynPageLoad=function(_options){      //发起数据请求模块
    var that=this;
    if(typeof(_options.container) == "string")
        that.vector=$(_options.container.indexOf("#")<0?"#":""+_options.container);
    else
        that.vector = _options.container;
    that.options={
        'url': "data.html",
        'getContent':null,
        'headers' : {'jycache-time': _options.cacheTime},
        'bottomH':200,
        'targetH':320,
        'maxWaitTime':15000,
        'oneTime':false,
        'patchData':null
    };
    that.options=$.extend(that.options,_options);
    that.createTip();
};

App.asynPageLoad.prototype={
    isRunning:false,
    waiting:0,
    curPage:1,
    curAjax:null,
    totalPage:-1,
    content: {},
    pcount: 10,
    enabled:false,
    pausing:false,
    tipDiv:$(),
    loadingEle:$(),
    pauseEle:$(),
    retryEle:$(),
    nomoreEle:$(),
    bindScrollToBottomEvent:function(){  /*是否浏览到底部的判断交给壳做，壳监听到后回调JS函数*/
        var that = this;
        window.slipjs.addCallback("endFun",function(){
            if(that.enabled && (this.wide_high - this.parent_wide_high + this.xy) <= that.options.bottomH){
                that.sendContent();
            }
        });
       /* NativeApp.registerHitPageBottomListener(function(){
            if(that.enabled)
                that.sendContent();
        },that.options.bottomH);*/

    },
    unbindScrollToBottomEvent:function(){
        /*NativeApp.registerHitPageBottomListener();*/
        window.slipjs.addCallback("endFun", null);
    },
    enable:function(){if(!this.pausing)this.enabled=true;},
    disable:function(){
        this.enabled=false;
        this.isRunning = false;
        if(this.curAjax)
            this.curAjax.abort();
    },
    beforeAjax:function(){
        if(this.isRunning){
            this.waiting++;
            return true;
        }
        this.isRunning=true;
        var tmp = this.options.getContent(this.curPage);//需要由getContent计算出pstart的数值
        this.content = tmp[0];
        this.pcount = tmp[1];
        this.curPage = tmp[2];
        return false;
    },
    afterAjax:function(eleLoadedNum){ //真表示 停止加载 假表示继续触发加载
        if(this.curPage == 1){
            if(this.options.floadEnded)
                this.options.floadEnded(eleLoadedNum);
        }
        if(this.options.oneTime)
            return true;
        var that=this;
        //that.loadingEle.hide();
        that.isRunning=false;
        if(eleLoadedNum < that.pcount || that.curPage == that.totalPage){
            that.unbindScrollToBottomEvent();  /*最后一页加载完后解除事件绑定*/
            that.loadingEle.hide();
            that.disable();
            if(that.curPage > 1){
                that.nomoreEle.show();
                setTimeout(function(){
                    //that.nomoreEle.hide();
                    that.tipDiv.hide();
                },1100);
            }else
                that.tipDiv.height(0);
            return true;
        }
        if(that.curPage%100!=0){   //暂时不做三页一停，故将数值调大
            that.curPage++;
            return false;
        }
        that.curPage++;
        that.loadingEle.hide();
        that.pauseEle.show();
        that.pausing=true;   //小憩一会
        that.disable();
        return true;
    },
    errorHandler:function(status){
        this.loadingEle.hide();
        this.isRunning=false;
        this.retryEle.show();
        this.pausing=true;
        this.disable();
        if(this.curPage == 1 && this.options.ferrorDeal)
            this.options.ferrorDeal(status);
    },
    tigger:function(){
        if(!this.options.oneTime) this.initialize();
        this.sendContent();
    },
    initialize:function(){
        this.enable();
        this.bindScrollToBottomEvent();
    },
    sendContent:function(){
        var that=this;
        if(that.beforeAjax())
            return;
        if(that.options.beforeLoad)
            that.options.beforeLoad();
        that.curAjax = $.ajax({
            type:'GET',
            url:that.options.url,
            data:that.content,
            headers:that.options.headers,
            success:function(data, status, xhr){
                var aIdx = data.indexOf('totalPage\":')+11,
                    bIdx = data.indexOf('curPageLen\":')+12,
                    cIdx = data.indexOf(",",bIdx);
                cIdx=cIdx<0?data.indexOf("}",bIdx):cIdx;
                var curPLen=parseInt(data.substring(bIdx,cIdx));
                that.totalPage=parseInt(data.substring(aIdx,data.indexOf(',',aIdx)));
                //数据分派处理
                that.options.patchData(data);
                if(that.options.afterLoad)
                    that.options.afterLoad.call(that);
                if(that.afterAjax(curPLen))
                    return;
                /*doc.documentElement.clientHeight 大于等于 doc.body.scrollHeight，说明当前页面还未出现滚动条*/
                //alert(doc.documentElement.clientHeight + "|" + doc.body.scrollHeight);
                if(that.enabled && (0 < that.waiting || !window.slipjs.isContentOverFlow())){
                    that.waiting -= (that.waiting >0 ? 1 : 0);
                    that.sendContent();
                }
            },
            error:function(httpRequest, textStatus){
                //NineGameClient.showMessage("failed: " + textStatus + " | " + JSON.stringify(httpRequest));
                that.errorHandler(textStatus);
                if(that.options.errorDeal)
                    that.options.errorDeal(textStatus);
            },
            dataType:'html',
            timeout:that.options.maxWaitTime
        });
    },
    restore:function(_fromPage){    /*页面切换Tab，各对象需重置*/
        this.bindScrollToBottomEvent();
        this.tipDiv.remove();
        this.createTip();
        this.curPage=_fromPage?_fromPage:1;
        this.pausing=false;
        this.restart();
    },
    restart:function(el){      /*页面重新恢复分页加载，发起请求*/
        var that=this;
        if(el){
            $(el).hide();
            that.loadingEle.show();
        }
        that.sendContent();
        that.enable();
    },
    createTip:function(){
        var that=this;
        if(that.options.oneTime || !that.vector || !that.options.tipSource)
            return;
        that.tipDiv=$(that.options.tipSource);
        that.loadingEle=that.tipDiv.children('[role=loading]');
        that.retryEle=that.tipDiv.children("[role=retry]");
        //that.nomoreEle=that.tipDiv.children("[role=nomore]");
        this.vector.after(that.tipDiv);
        that.pauseEle.bind("click",function(){that.pausing=false;that.restart(this);});
        $(that.retryEle.children()[0]).bind("click",function(){that.pausing=false;that.restart(this.parentNode);});
    },
    setUrl:function(turl){
        this.options.url=turl;
    },
    setHeader:function(header){
        this.options.headers=header;
    },
    setMaxWaitTime:function(time){
        this.options.maxWaitTime=time;
    }
};
/*Requester._options形参：
 params:_options.container    分页内容装载容器
 params:_options.cacheTime  请求数据页缓存时间
 params:_options.floadEnded 分页数据第一次返回成功时回调
 params:_options.ferrorDeal 分页数据第一次返回失败时回调
 */
App.Requester.init = function(_options){
    _options = $.extend({      //使用特殊默认值
        url: BaseConf.host + BaseConf.dataApi,
        getContent: App.getContent,
        cacheTime: BaseConf.cacheTime,
        patchData: App.dispatch,
        targetH: targetHeight,
        tipSource: loadTipTpl,
        floadEnded: LoadFrame.success,
        ferrorDeal: LoadFrame.failed
    },_options);
    var initR = App.Requester.init;
    exports.Requester = App.Requester = new App.asynPageLoad(_options);
    App.Requester.init = initR;  //还原init函数
};

exports.Requester = App.Requester;

exports.Model = App.Model ={
    'key': "z110",
    'orgkey': "110",
    'private': 0,
    'prefix': '',
    'params': "",
    'commonParams': "",
    'cacheKey': null,
    getCacheMethod: null,    //缓存数据读取接口定义
    getKey: function(){return this.key;},
    getParams: function(){return this.params;},
    getCacheKey: function(){return this.cacheKey;},
    getOrgkey:function(){return this.orgkey;},
    replaceConnStr: function(_orgStr){
        var that = this;
        return _orgStr.replace(/(=)|(&)/g,function(m,orgEq,orgAnd){
            if(orgEq)
                return '|';
            return '^';
        });

    },
    setBase: function(_options){
        this.commonParams = _options.commonParams || this.commonParams;
        if(this.commonParams){
            this.commonParams=this.replaceConnStr(this.commonParams);
            App.UpdateState++;
        }
        this.getCacheMethod = _options.getCacheMethod || this.getCacheMethod;
    },
    extend: function(_options){
        _options.key = _options.key || this.key;
        _options.orgkey = _options.key;
        _options['private'] = _options['private'] || this['private']; //private为保留关键词小心使用
        _options.cacheKey = _options.cacheKey || this.cacheKey;
        _options.getKey = _options.getKey || this.getKey;
        _options.getParams = _options.getParams || this.getParams;
        _options.getCacheKey = _options.getCacheKey || this.getCacheKey;
        _options.getOrgkey = _options.getOrgkey || this.getOrgkey;
        _options.prefix = this.prefix;
        var prefix = null;
        if(_options['private']){
            prefix = String.fromCharCode(App.PreSeed++);
            _options.key = prefix + _options.key;
            _options.prefix = prefix;
        }
        if(prefix && _options.params){ //待改进
            _options.params = _options.params.replace(/([^&]+=)/gi,function(m,pkey){
                return prefix+"-"+pkey;
            });
            _options.params = this.replaceConnStr(_options.params);
        }else
            _options.params = this.params;
        return _options;
    }
};
exports.View = App.View = {
    'container': null,
    'ptext': "unknown",
    'htmlFrag':"<>",
    render: function(_data,_fromPage){console.log(" view render from "+_fromPage+" page");},
    extend: function(_options){
        _options.container = _options.container || this.container;
        _options.ptext = _options.ptext || this.ptext;
        _options.htmlFrag = _options.htmlFrag || this.htmlFrag;
        _options.render = _options.render || this.render;
        return _options;
    }
};
/*addModule形参：
 params:_moduleName 模块名称
 params:_model  数据块Model实例
 params:_view   视图控制View实例
 params:_onceLife 是否是一次性用途，即render之后模块自动移除
 params:_enabled 数据源请求通道是否开启,默认是开启状态
 */
exports.addModule=function(_moduleName,_model,_view,_onceLife,_enabled){
    var key = _model.getKey();
    _enabled = (typeof(_enabled) =="undefined")?true:_enabled;
    App.KeyToModuleName[key] =_moduleName;
    App.Modules[_moduleName] = {"Model":_model,"View":_view,"onceLife":_onceLife || false, "enabled": _enabled};
    App.Routes[key] = _view;
    App.UpdateState++;
    var cacheKey = _model.getCacheKey();
    if(_enabled && cacheKey && App.Model.getCacheMethod){ //通道已开启 且cache键 和 缓存数据方法都已定义
        App.dispatch(App.jsonStrPackage(key,App.Model.getCacheMethod(cacheKey)));
    }
};
exports.removeModule = App.removeModule = function(_moduleName){
    var key = null;
    if(App.Modules[_moduleName]){
        key = App.Modules[_moduleName].Model.getKey();
        delete App.Modules[_moduleName];
        App.UpdateState++;
    }
    if(key && App.Routes[key])
        delete App.Routes[key];
};
exports.enableModule=function(_moduleName){
    if(App.Modules[_moduleName] && !App.Modules[_moduleName].enabled){
        App.Modules[_moduleName].enabled=true;
        App.UpdateState++;
    }
};
exports.disableModule=function(_moduleName){
    if(App.Modules[_moduleName] && App.Modules[_moduleName].enabled){
        App.Modules[_moduleName].enabled=false;
        App.UpdateState++;
    }
};
App.getParamVal=function(_paramStr,_key,_prefix){    //优先匹配专有通道 如果未找到则在公用参数中找
    var res = null;
    if(_prefix)               //带有专属通道的参数值获取
        res=_paramStr.match(eval('/('+_prefix+'\\-'+_key+')\\|([^\\^]+)/'));
    if(!res)                      //公用参数值的获取
        res=_paramStr.match(eval('/(^|[\\^])'+_key+'\\|([^\\^]+)/'));
    return res?res[2]:null;
};
App.setParamVal=function(_paramStr,_key,_val,_prefix){
    var non = true,
        fullKey = _key;
    if(_prefix){                //带有专属通道的参数值的设置
        fullKey = _prefix + '-' + _key;
        _paramStr=_paramStr.replace(eval('/('+_prefix+'\\-'+_key+')\\|([^\\^]+)/'),function(m,orgKey,orgVal){
            non = false;
            return orgKey + "|" + _val;
        });
    }else{                      //公用参数值的设置
        _paramStr=_paramStr.replace(eval('/(^'+_key+'|\\^'+_key+')\\|([^\\^]+)/'),function(m,orgKey,orgVal){
            non = false;
            return orgKey + "|" + _val;
        });
    }
    if(non)     //在专有通道以及公用参数中都未出现过则新添加
        _paramStr += (_paramStr?'^':'') + fullKey + '|' + _val;
    return _paramStr;
};
/*getContent形参：
 params:_currPage 分页加载时当前的页码
 返回值:
 return: 1 用于向后端发起请求时的参数组合
 return: 2 当前分页模块每页加载的条数
 return: 3 如果分页模块更换需要从第一页加载数据
 */
App.getContent=function(_currPage){
    _currPage = _currPage || 1;           //置默认值为1
    if(!App.UpdateState){
        var tmp = App.BuildContent;
        return [{'key':tmp.key,'params':App.setParamVal(tmp.params,"pstart",(_currPage-1)*tmp.pcount,tmp.prefix)},tmp.pcount,_currPage];
    }
    var keys = "",
        params = "",
        CModel = App.Model,
        iter = 0,
        itPrefix = '',
        itKeycode = '';
    for(var m in App.Modules){
        var module = App.Modules[m];
        if(!module.enabled)       //通道未开启
            continue;
        var tmodel = module.Model,
            keycode = tmodel.getKey();
        keys += (keys?"-":"") + keycode;
        if(tmodel.getParams() != "")
            params += (params?"^":"") + tmodel.getParams();
        if(0 == parseInt(tmodel.getOrgkey())%10 || !iter){  /*末尾带0或是第一个满足条件的Model ps:!parseInt(tmodel.getOrgkey())%10不能达到相同效果？*/
            itPrefix = tmodel.prefix;
            itKeycode = keycode;
        }
        iter++;
    }
    //alert(itPrefix);
    if(CModel.commonParams)
        params += (params?"^":"") + CModel.commonParams;
    var pcount = App.getParamVal(params,'pcount',itPrefix);
    pcount = parseInt(pcount) || 10;       //得到用于分页模块的每页数量
    //alert(pcount);
    if(itKeycode != App.BuildContent.keycode)   //分页模块发生改变，则从第一页开始加载
        _currPage = 1;
    params = App.setParamVal(params,"pstart",(_currPage-1)*pcount,itPrefix);
    App.UpdateState = 0;
    App.BuildContent = {'key':keys,'params':params,'pcount':pcount,'prefix':itPrefix,'keycode':itKeycode};
    return [{'key':keys,'params':params},pcount,_currPage];
};
App.jsonStrPackage=function(_key,_jsonStr){     //最外层一定要用单引号不然报错
    return '{"column_ary":[{"col_name": "'+_key+'","data_frag": [' + _jsonStr + '],"data_idx":1}]}';
};
App.dispatch=function(_data){
    try{
        var food=JSON.parse(_data.trim());
        var collist=food.column_ary;
        for(var i=0;i < collist.length;i++){
            var colobj = collist[i],
                tView = null,
                tkey = colobj.col_name;
            if((tView=App.Routes[tkey])!= undefined){
                try{                           //data_idx为另一个维度的参照值
                    var moduleName = App.KeyToModuleName[tkey];
                    if(App.Modules[moduleName].enabled){    //如果当前模块仍为可用的，则渲染
                        tView.render(colobj.data_frag,colobj.total);
                        if(App.Modules[moduleName].onceLife)    //一次性用途
                            App.removeModule(moduleName);
                    }
                }catch(e){
                    console.log("路由事件执行错误："+tkey+"|" + e.toString());
                }
            }
        }
    }catch(e){
        console.log("返回JSON格式错误："+ e.toString());
    }
};

